from webutils.layers.services import ManagerProxy

from .. import const, managers
from .base import BaseService


class ChatService(BaseService):
    group_enum_cls = const.UserGroup
    text_chat_lst = ManagerProxy(managers.TextChat)
    image_chat_lst = ManagerProxy(managers.ImageChat)
    group_blacklist = ManagerProxy(managers.GroupBlacklist)
    user_blacklist = ManagerProxy(managers.UserBlacklist)

    async def append_text_message(self, message):
        assert 'chat_id' not in message
        chat_id = await self.text_chat_lst.append(message)
        message['chat_id'] = chat_id
        await self.text_chat_lst.update(chat_id - 1, message)
        message.pop('chat_id')
        return chat_id

    async def get_text_message_count(self):
        return await self.text_chat_lst.count()

    async def get_text_message_lst(self, start, end, sort='asc'):
        lst = await self.text_chat_lst.slicing(start, end=end)
        if sort != 'asc':
            lst = list(reversed(lst))
        return lst

    async def append_image_message(self, message):
        chat_id = await self.append_text_message(message)
        message['chat_id'] = chat_id
        await self.text_chat_lst.append(message)
        return chat_id

    async def get_image_message_count(self):
        return await self.image_chat_lst.count()

    async def get_image_message_lst(self, start, end, sort='asc'):
        lst = await self.image_chat_lst.slicing(start, end=end)
        if sort != 'asc':
            lst = list(reversed(lst))
        return lst

    async def block_user(self, user_id, user_info=None):
        user_info = user_info or {}
        await self.user_blacklist.add(user_id, user_info)

    async def unblock_user(self, user_id):
        await self.user_blacklist.remove(user_id)

    async def get_blocked_users(self):
        dct = await self.user_blacklist.all()
        return {key.decode(): value for key, value in dct.items()}

    async def block_group(self, group, group_info=None):
        assert isinstance(group, self.group_enum_cls)
        group_info = group_info or {}
        await self.group_blacklist.add(group.value, group_info)

    async def unblock_group(self, group):
        assert isinstance(group, self.group_enum_cls)
        await self.group_blacklist.remove(group.value)

    async def get_blocked_groups(self):
        dct = await self.group_blacklist.all()
        return {
            self.group_enum_cls(key.decode()): value
            for key, value in dct.items()
        }

    async def is_user_blocked(self, user_id, user_group):
        assert isinstance(user_group, self.group_enum_cls)
        if await self.user_blacklist.exists(user_id):
            return True
        if await self.group_blacklist.exists(user_group.value):
            return True
        if await self.group_blacklist.exists(self.group_enum_cls.ALL.value):
            return True
        return False
